feat(mobile): enable session replay and align analytics with desktop#2633
Conversation
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
|
| describe("registerPersistentSuperProperties", () => { | ||
| it("registers team and app_version as super properties on the PostHog client", async () => { | ||
| const register = vi.fn(); | ||
| const { registerAppVersion } = await import("./posthog"); | ||
| const { registerPersistentSuperProperties } = await import("./posthog"); | ||
|
|
||
| registerAppVersion({ register }, "1.2.3"); | ||
| registerPersistentSuperProperties({ register }, "1.2.3"); | ||
|
|
||
| expect(register).toHaveBeenCalledTimes(1); | ||
| expect(register).toHaveBeenCalledWith({ app_version: "1.2.3" }); | ||
| expect(register).toHaveBeenCalledWith({ | ||
| team: "posthog-code", | ||
| app_version: "1.2.3", | ||
| }); | ||
| }); | ||
|
|
||
| it("does nothing when the PostHog client is not yet available", async () => { | ||
| const { registerAppVersion } = await import("./posthog"); | ||
| const { registerPersistentSuperProperties } = await import("./posthog"); | ||
|
|
||
| expect(() => registerAppVersion(null, "1.2.3")).not.toThrow(); | ||
| expect(() => | ||
| registerPersistentSuperProperties(null, "1.2.3"), | ||
| ).not.toThrow(); | ||
| }); | ||
|
|
||
| it("does nothing when no app version can be resolved", async () => { | ||
| it("still registers team when no app version can be resolved", async () => { | ||
| const register = vi.fn(); | ||
| const { registerAppVersion } = await import("./posthog"); | ||
| const { registerPersistentSuperProperties } = await import("./posthog"); | ||
|
|
||
| registerAppVersion({ register }, null); | ||
| registerPersistentSuperProperties({ register }, null); | ||
|
|
||
| expect(register).not.toHaveBeenCalled(); | ||
| expect(register).toHaveBeenCalledTimes(1); | ||
| expect(register).toHaveBeenCalledWith({ team: "posthog-code" }); | ||
| }); | ||
|
|
||
| it("resolves the version from getAppVersion when none is provided", async () => { | ||
| expoApplication.nativeApplicationVersion = "4.5.6"; | ||
| const register = vi.fn(); | ||
| const { registerAppVersion } = await import("./posthog"); | ||
| const { registerPersistentSuperProperties } = await import("./posthog"); | ||
|
|
||
| registerAppVersion({ register }); | ||
| registerPersistentSuperProperties({ register }); | ||
|
|
||
| expect(register).toHaveBeenCalledWith({ app_version: "4.5.6" }); | ||
| expect(register).toHaveBeenCalledWith({ | ||
| team: "posthog-code", | ||
| app_version: "4.5.6", | ||
| }); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Prefer parameterised tests for the
registerPersistentSuperProperties suite
Three of the four cases here test the same code path (client present, call register) and differ only in the version input and the expected properties object. Per the team's simplicity rules, consolidating them into a single it.each table (e.g., [version, expected]) removes the repeated vi.fn() / import / expect boilerplate and makes it easier to add a new combination in the future.
Context Used: Do not attempt to comment on incorrect alphabetica... (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/mobile/src/lib/posthog.test.ts
Line: 81-125
Comment:
**Prefer parameterised tests for the `registerPersistentSuperProperties` suite**
Three of the four cases here test the same code path (client present, call `register`) and differ only in the `version` input and the expected properties object. Per the team's simplicity rules, consolidating them into a single `it.each` table (e.g., `[version, expected]`) removes the repeated `vi.fn()` / `import` / `expect` boilerplate and makes it easier to add a new combination in the future.
**Context Used:** Do not attempt to comment on incorrect alphabetica... ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Problem
The mobile app's PostHog instrumentation has several gaps that leave us blind on errors, replays, and identity:
enableSessionReplay: truehas been set since January, but the required companion native packageposthog-react-native-session-replaywas never installed, so the SDK silently no-ops — zero recordings have ever been ingested.maskAllTextInputs: falsewould capture credentials typed on the auth screen once replay starts working.team: "posthog-code"super property; mobile events lack that property, so they can't be segmented alongside desktop's once consolidated.Changes
posthog-react-native-session-replay@1.6.0so session replay actually records (verified it links natively via pod install).maskAllTextInputs: truein the replay config.registerAppVersionwithregisterPersistentSuperProperties, which always registersteam: "posthog-code"(matching desktop) plusapp_versionwhen available, and is re-applied afterposthog.reset()on logout since reset wipes super properties.Sign in started/Sign in completed/Sign in failedevents across all three sign-in paths (OAuth, dev API key, QR scan) withmethod,region, and failurereason(cancelled / timeout / error) properties.apps/mobile/.env.exampledocumenting the PostHog env vars.Note: this only takes effect once a new build ships. Repointing
EXPO_PUBLIC_POSTHOG_API_KEYin the EAS production environment to the shared project is a separate operational step.How did you test this?
pnpm testinapps/mobile: 263 tests pass, including new coverage for theteamsuper property inposthog.test.ts.tsc --noEmit: no errors in changed files.biome check: clean.pod installinapps/mobile/ios: confirmsposthog-react-native-session-replay (1.6.0)and nativePostHog (3.58.3)link via autolinking.Automatic notifications